package ikelib;

import ikeuilib.DirectoryChooser;
import ikeuilib.JProgressCellRenderer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * 計算式を数値に変換できるテキストフィールド
 * @author ikechan
 *
 */
public class NumericTextField extends JTextField implements MouseListener{
	/**
	 * 
	 */
	
	private static final long serialVersionUID = 1L;
	private int OutputType = 0; // 0: Long 1: Double
	private Vector<String> Original = new Vector();
	private int OriginalIndex=0;
	private JMenuItem MenuUndo = null;
	/**
	 * 
	 */
	public NumericTextField(){
		super();
		super.setBackground(new Color(255,250,250));
		Font f = super.getFont();
		
		super.setFont(f.deriveFont(Font.BOLD));
		addPopupMenuItem(contextMenu,"Evaluate as Integer (CTRL+ENTER)",null, new ActionListener(){ 
			@Override
			public void actionPerformed(ActionEvent arg0) {
				OutputType=0;
				setText(getText());
			}
	       });	
		addPopupMenuItem(contextMenu,"Evaluate as Floating point (SHIFT+ENTER)",null, new ActionListener(){ 
			@Override
			public void actionPerformed(ActionEvent arg0) {
				OutputType=1;
				setText(getText());
			}
	       });	
		contextMenu.addSeparator();
		addPopupMenuItem(contextMenu,"Undo (CTRL+z)",null, new ActionListener(){ 
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Undo();
			}
	    });	
		setComponentPopupMenu(contextMenu);
		addMouseListener(this);
		setToolTipText("<html><h4>Numeric Text Feild</h4><br>" +
				"<p>Write numerical expression;+,-,*,/,(,),log,ln,sin,asin,cos,acos,tan,atan,sqrt,PI.<br>" +
				"Then evaluate it from context(right click) menu.</p></html>");
		addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if(e.getKeyChar() == KeyEvent.VK_ENTER){
					if(e.getModifiers() == KeyEvent.CTRL_MASK){
						convInteger();
					}
					else if(e.getModifiers() == KeyEvent.SHIFT_MASK){
						convFloat();
					}
					else{
						OutputType=0;
						setText(getText());
					}
					
				}
				else if(e.getKeyCode() == KeyEvent.VK_Z){
					if(e.getModifiers() == KeyEvent.CTRL_MASK){
						Undo();
					}
				}
			}

		});
		
	}
	/**
	 * 整数表現に可能なら変換する
	 */
	private void convInteger() {
		String str  = getText();
		try{
			double d = Double.valueOf(str);
			if(d - Math.ceil(d) == 0.0){
				String s = String.format("%.0f", d);
				setText(s);
			}
		}
		catch(NumberFormatException e){
		}
	}
	/**
	 * 浮動小数点表現に変換する
	 */
	private void convFloat(){
		String str  = getText();
		try{
			double d = Double.valueOf(str);
			String s = String.format("%e", d);
			setText(s);
		}
		catch(NumberFormatException e){
			
		}
	}
	
	
	/**
	 * ポップアップメニューを追加する補助関数
	 * @param pum
	 * @param name
	 * @param imageFile
	 * @param al
	 * @return
	 */
	private JMenuItem addPopupMenuItem(JPopupMenu pum,String name, String imageFile,ActionListener al) {
		JMenuItem item = new JMenuItem(name);
		if(imageFile!=null) item.setIcon(new ImageIcon(getClass().getClassLoader().getResource(imageFile)));
		item.addActionListener(al);
		pum.add(item);
		return item;
	}
	/**
	 * getTextのオーバーライド
	 */
	public String getText(){
		String txt = super.getText();
		if(txt==null) return "";
		if(txt.isEmpty()) return "";
		if(txt.contains(",")){
			String txt2 = new String();
			for(int i=0;i<txt.length();i++){
				char c = txt.charAt(i);
				if(c!=','){
					txt2 += c;
				}
			}
			txt = txt2;
		}
		Original.add( txt);
		OriginalIndex++;
		// 一度intで試してみてエラーならDoubleに切替え
		try{
			int itmp = Integer.valueOf(txt);
		}catch(NumberFormatException e){
			OutputType=1;
		}
		
		Double dd=0.0;
		try{
			dd = Double.valueOf(txt);
			if(OutputType==0){
				txt = String.format("%.0f", dd);
			}
			else{
				txt = String.format("%e", dd);
			}
		} catch (NumberFormatException e){
			if(txt.charAt(txt.length()-1)!='='){
				txt = txt + "=";
			}
			String txt2 = "";
			for(int i=0;i<txt.length();i++){
				if(txt.charAt(i)!=',') txt2 += txt.charAt(i);
			}
			txt  =txt2.replace('e', 'E');
			StringParser sp = new StringParser(txt);
			if(sp.check_str()){
				dd = sp.calculate();
				if(OutputType==0){
					txt = String.format("%.0f", dd);
				}
				else{
					txt = String.format("%e", dd);
				}
			}
		}
		
		return txt;
	}
	/**
	 * 
	 */
	private transient JPopupMenu contextMenu = new JPopupMenu();
	
	@Override
	public void mouseClicked(MouseEvent e) { 
		if (SwingUtilities.isRightMouseButton(e)) {
			contextMenu.setVisible(true);
		}
	}
	@Override
	public void mouseEntered(MouseEvent arg0) {
		
	}
	@Override
	public void mouseExited(MouseEvent arg0) {
		
	}
	@Override
	public void mousePressed(MouseEvent arg0) {
		
	}
	@Override
	public void mouseReleased(MouseEvent arg0) {
		
	}
	/**
	 * 
	 */
	private void Undo() {
		if(Original!=null){
			if(!Original.isEmpty()){
				// undoをいくつでもできるようにする。
				if(Original.size()<=OriginalIndex){
					int index  = Original.size()-1;
					String str = Original.get(index);
					Original.remove(index);
					OriginalIndex--;
					setText(str);
				}
			}
		}
	}
	public static void main(String[] arg){
		JFrame f=new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		NumericTextField t = new NumericTextField();
		f.getContentPane().add(t);
		f.setTitle("Test");
		f.setSize(300,70);
		f.setLocationRelativeTo(null);
		f.setVisible(true);

	}
}
